<script lang="ts" setup>
import type { FileUploadItem, UploadOptions } from './types';

import { nextTick, ref, watch } from 'vue';

import { fileTransfer } from '../../api/core/client';
import FileDropZone from './FileDropZone.vue';
import FileUploadQueue from './FileUploadQueue.vue';
import MessageInput from './MessageInput.vue';

interface Props {
  maxFileSize?: number;
  acceptedTypes?: string[];
  multiple?: boolean;
  chunkSize?: number;
  maxRetry?: number;
  autoUpload?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  maxFileSize: 100 * 1024 * 1024, // 100MB
  acceptedTypes: undefined,
  multiple: true,
  chunkSize: 1024 * 1024, // 1MB
  maxRetry: 3,
  autoUpload: false,
});

const emit = defineEmits<{
  error: [message: string];
  uploadComplete: [items: FileUploadItem[]];
  uploadProgress: [items: FileUploadItem[]];
}>();

// 状态管理
const uploadQueue = ref<FileUploadItem[]>([]);
const isUploading = ref(false);
const uploadMessage = ref('');
const currentUploadTasks = new Map<string, AbortController>();

// 生成唯一ID
const generateId = () => {
  return `upload_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
};

// 添加文件到队列
const addFilesToQueue = (files: File[]) => {
  const newItems: FileUploadItem[] = files.map((file) => ({
    id: generateId(),
    name: file.name,
    size: file.size,
    file,
    status: 'pending',
  }));

  // 检查是否有重复文件
  for (const newItem of newItems) {
    const exists = uploadQueue.value.some(
      (item) => item.name === newItem.name && item.size === newItem.size,
    );

    if (!exists) {
      uploadQueue.value.push(newItem);
    }
  }

  // 如果启用自动上传，立即开始上传
  if (props.autoUpload && !isUploading.value) {
    nextTick(() => {
      startUpload();
    });
  }

  emit('uploadProgress', [...uploadQueue.value]);
};

// 移除文件
const removeItem = (id: string) => {
  // 如果正在上传，先取消
  if (currentUploadTasks.has(id)) {
    cancelItem(id);
  }

  uploadQueue.value = uploadQueue.value.filter((item) => item.id !== id);
  emit('uploadProgress', [...uploadQueue.value]);
};

// 取消上传
const cancelItem = (id: string) => {
  const controller = currentUploadTasks.get(id);
  if (controller) {
    controller.abort();
    currentUploadTasks.delete(id);
  }

  const item = uploadQueue.value.find((item) => item.id === id);
  if (item && item.status === 'uploading') {
    item.status = 'cancelled';
    item.error = '用户取消上传';
  }

  emit('uploadProgress', [...uploadQueue.value]);
};

// 重试上传
const retryItem = (id: string) => {
  if (id === 'all-failed') {
    // 重试所有失败的文件
    const failedItems = uploadQueue.value.filter(
      (item) => item.status === 'error',
    );
    for (const item of failedItems) {
      item.status = 'pending';
      item.error = undefined;
      item.progress = undefined;
    }

    if (!isUploading.value) {
      startUpload();
    }
  } else {
    // 重试单个文件
    const item = uploadQueue.value.find((item) => item.id === id);
    if (item) {
      item.status = 'pending';
      item.error = undefined;
      item.progress = undefined;

      if (!isUploading.value) {
        uploadSingleFile(item);
      }
    }
  }

  emit('uploadProgress', [...uploadQueue.value]);
};

// 清空队列
const clearAll = () => {
  // 取消所有正在进行的上传
  for (const [id] of currentUploadTasks) {
    cancelItem(id);
  }

  uploadQueue.value = [];
  isUploading.value = false;
  emit('uploadProgress', []);
};

// 暂停上传
const pauseUpload = () => {
  isUploading.value = false;

  // 取消所有正在进行的上传
  for (const [id] of currentUploadTasks) {
    cancelItem(id);
  }
};

// 上传单个文件
const uploadSingleFile = async (item: FileUploadItem) => {
  if (item.status !== 'pending') return;

  try {
    item.status = 'uploading';
    item.progress = undefined;
    item.error = undefined;

    // 创建取消控制器
    const controller = new AbortController();
    currentUploadTasks.set(item.id, controller);

    // 创建上传实例
    const uploader = fileTransfer.createUpload(props.chunkSize);

    // 准备上传选项
    const options: UploadOptions = {
      chunkSize: props.chunkSize,
      maxRetry: props.maxRetry,
      message: uploadMessage.value,
    };

    // 开始上传
    const uploadedId = await uploader.uploadFile(item.file, {
      chunkSize: options.chunkSize,
      onProgress: (progressInfo) => {
        if (controller.signal.aborted) return;

        item.progress = progressInfo;
        emit('uploadProgress', [...uploadQueue.value]);
      },
    });

    // 上传成功
    if (!controller.signal.aborted) {
      item.status = 'success';
      item.uploadedId = uploadedId;
      currentUploadTasks.delete(item.id);
    }
  } catch (error) {
    if (!currentUploadTasks.get(item.id)?.signal.aborted) {
      item.status = 'error';
      item.error = error instanceof Error ? error.message : '上传失败';
      currentUploadTasks.delete(item.id);
    }
  }

  emit('uploadProgress', [...uploadQueue.value]);
};

// 开始上传
const startUpload = async () => {
  if (isUploading.value) return;

  const pendingItems = uploadQueue.value.filter(
    (item) => item.status === 'pending',
  );
  if (pendingItems.length === 0) return;

  isUploading.value = true;

  try {
    // 并发上传多个文件（最多3个）
    const maxConcurrent = 3;
    const uploading: Promise<void>[] = [];

    for (const item of pendingItems) {
      if (!isUploading.value) break;

      // 控制并发数量
      if (uploading.length >= maxConcurrent) {
        await Promise.race(uploading);
        // 移除已完成的任务
        for (let i = uploading.length - 1; i >= 0; i--) {
          const promise = uploading[i];
          if (
            (await Promise.race([promise, Promise.resolve('pending')])) !==
            'pending'
          ) {
            uploading.splice(i, 1);
          }
        }
      }

      const uploadPromise = uploadSingleFile(item);
      uploading.push(uploadPromise);
    }

    // 等待所有上传完成
    await Promise.allSettled(uploading);
  } finally {
    isUploading.value = false;

    // 检查是否全部上传完成
    const completedItems = uploadQueue.value.filter(
      (item) => item.status === 'success' || item.status === 'error',
    );

    if (completedItems.length === uploadQueue.value.length) {
      emit('uploadComplete', [...uploadQueue.value]);
    }
  }
};

// 处理错误
const handleError = (message: string) => {
  emit('error', message);
};

// 监听上传消息变化
watch(uploadMessage, () => {
  emit('uploadProgress', [...uploadQueue.value]);
});
</script>

<template>
  <div class="space-y-6">
    <!-- 文件拖放区域 -->
    <FileDropZone
      :max-file-size="maxFileSize"
      :accepted-types="acceptedTypes"
      :multiple="multiple"
      :disabled="isUploading"
      @files-selected="addFilesToQueue"
      @error="handleError"
    />

    <!-- 留言输入 -->
    <MessageInput v-model="uploadMessage" :disabled="isUploading" />

    <!-- 上传队列 -->
    <FileUploadQueue
      :items="uploadQueue"
      :is-uploading="isUploading"
      @start-upload="startUpload"
      @pause-upload="pauseUpload"
      @remove-item="removeItem"
      @retry-item="retryItem"
      @cancel-item="cancelItem"
      @clear-all="clearAll"
    />
  </div>
</template>
